package com.xframe.xdal.core.model.mapping;

import com.xframe.xdal.core.annotation.AutoFill;
import com.xframe.xdal.core.annotation.AutoFillBean;
import com.xframe.xdal.core.annotation.XColumn;
import com.xframe.xdal.core.autofill.IAutoFillBean;
import com.xframe.xdal.core.constant.AutoFillType;
import com.xframe.xdal.core.util.StringUtil;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 功能描述:列的映射信息
 *
 * @author xufeng
 * @version 1.0
 * @date 2022-09-26
 */
public class ColumnMapping implements IColumnMapping {


    /**
     * 列名称
     */
    private String name;

    /**
     * 获取字段原始名称
     */
    private String fieldName;
    /**
     * 列描述
     */
    private String desc;
    /**
     * 是否主键
     */
    private boolean primaryKeyFlag = false;
    /**
     * 是否唯一索引
     */
    private boolean uniqueFlag = false;
    /**
     * 唯一标识名字(名字相同的是一组)
     */
    private String uniqueName = "MAIN";
    /**
     * 是否使用的数据库表达式
     */
    private boolean useDbObjectFlag = false;
    /**
     * 使用的数据库表达式
     */
    private String dbExpression = "";
    /**
     * 列类型
     */
    private Class<?> dataType;
    /**
     * 数据库字段的长度
     */
    private Integer length = 0;
    /**
     * 是否删除标识
     */
    private boolean deleteFlag = false;
    /**
     * 是否可以为空
     */
    private boolean nullFlag = true;
    /**
     * 是否包含数据库自动生成的值
     */
    private boolean dbGeneratedFlag = false;
    /**
     * 是否版本号(并发冲突使用)
     */
    private boolean versionFlag = false;

    /**
     * 是否只读
     */
    private boolean readonly;

    /**
     * 唯一键名称
     */
    private String akGroupName;

    /**
     * 小数位
     */
    private Integer scale = 0;


    private List<IAutoFillBean> autoFillBeanList;

    /**
     * 获得对该列上自动填充对象列表
     *
     * @return 自动填充对象列表
     */
    @Override
    public List<IAutoFillBean> getAutoFillBeanList(){
        return this.autoFillBeanList;
    }

    /**
     * 根据注解和对象的字段来构造数据库列映射信息
     *
     * @param column 数据库枚举
     * @param field 字段
     * @return ColumnMapping
     */
    public static ColumnMapping valueOf(XColumn column, Field field){
        ColumnMapping columnMapping = new ColumnMapping();
        columnMapping.name = StringUtil.isEmpty(column.name())?StringUtil.camelToUnderScoreCase(field.getName()):column.name();
        columnMapping.primaryKeyFlag = column.primaryKeyFlag();

        columnMapping.akGroupName = column.akGroupName();
        columnMapping.useDbObjectFlag = column.useDbObjectFlag();
        columnMapping.dbExpression = column.dbExpression();
        columnMapping.dbGeneratedFlag = column.dbGeneratedFlag();
        columnMapping.desc = column.desc();
        columnMapping.nullFlag = column.nullFlag();
        columnMapping.deleteFlag = column.deleteFlag();
        columnMapping.uniqueFlag = column.uniqueFlag();
        columnMapping.versionFlag = column.versionFlag();
        columnMapping.readonly = column.readonly();
        columnMapping.dataType = field.getType();
        columnMapping.fieldName = field.getName();
        columnMapping.length = column.length();
        columnMapping.scale = column.scale();
        columnMapping.uniqueName = column.uniqueName();
        columnMapping.autoFillBeanList = new ArrayList<>();
        AutoFill[] autoFills = field.getAnnotationsByType(AutoFill.class);
        if(autoFills.length > 0){
            for(AutoFill autoFill : autoFills) {
                columnMapping.autoFillBeanList.add(AutoFillBean.valueOf(autoFill,field));
            }
            Collections.sort(columnMapping.autoFillBeanList);
        }
        return columnMapping;
    }


    public static ColumnMapping valueOf(String name, boolean primaryKeyFlag,String akGroupName,
                                        boolean useDbObjectFlag,
                                        String dbExpression,
                                        boolean dbGeneratedFlag,String desc,boolean nullFlag,
                                        boolean deleteFlag,boolean uniqueFlag,boolean versionFlag,
                                        boolean readonly,Class<?> dataType,String fieldName,Integer length,Integer scale,
                                        List<IAutoFillBean> autoFillBeanList){
        ColumnMapping columnMapping = new ColumnMapping();
        columnMapping.name = name;
        columnMapping.primaryKeyFlag = primaryKeyFlag;
        columnMapping.akGroupName = akGroupName;
        columnMapping.useDbObjectFlag = useDbObjectFlag;
        columnMapping.dbExpression = dbExpression;
        columnMapping.dbGeneratedFlag = dbGeneratedFlag;
        columnMapping.desc = desc;
        columnMapping.nullFlag = nullFlag;
        columnMapping.deleteFlag = deleteFlag;
        columnMapping.uniqueFlag = uniqueFlag;
        columnMapping.versionFlag = versionFlag;

        columnMapping.readonly = readonly;
        columnMapping.dataType = dataType;
        columnMapping.fieldName = fieldName;
        columnMapping.length = length;
        columnMapping.scale = scale;
        columnMapping.autoFillBeanList = autoFillBeanList;
        return columnMapping;
    }


    public static ColumnMapping valueOfPk(String name,String desc,
                                       Class<?> dataType,String fieldName){
        List<IAutoFillBean> autoFillBeanList = new ArrayList<>();
        autoFillBeanList.add(AutoFillBean.valueOf(AutoFillType.Snowflake));
        return valueOf(name,true,"",false,"",false,desc,
                false,false,false,false,false,dataType,fieldName,0,0,autoFillBeanList);
    }

    public static ColumnMapping valueOfAk(String name,String desc,
                                          Class<?> dataType,String fieldName,Integer length){
        List<IAutoFillBean> autoFillBeanList = new ArrayList<>();
        return valueOf(name,false,"",false,"",false,desc,
                false,false,true,false,false,dataType,fieldName,length,0,autoFillBeanList);
    }

    public static ColumnMapping valueOf(String name,
                                        String desc,boolean nullFlag,
                                        Class<?> dataType,String fieldName,Integer length,Integer scale){

        return valueOf(name,false,"",false,"",false,
                desc,nullFlag,false,false,false,false,dataType,fieldName,length,scale,new ArrayList<>());
    }

    public static ColumnMapping valueOf(String name,
                                        String desc,boolean nullFlag,
                                        Class<?> dataType,String fieldName,Integer length){

        return valueOf(name,false,"",false,"",false,
                desc,nullFlag,false,false,false,false,dataType,fieldName,length,0,new ArrayList<>());
    }

    public static ColumnMapping valueOf(String name,
                                        String desc,boolean nullFlag,
                                        Class<?> dataType,String fieldName,Integer length,AutoFillBean autoFillBean){

        List<IAutoFillBean> autoFillBeanList = new ArrayList<>();
        autoFillBeanList.add(autoFillBean);
        return valueOf(name,false,"",false,"",false,
                desc,nullFlag,false,false,false,false,dataType,fieldName,length,0,autoFillBeanList);
    }

    public static ColumnMapping valueOf(String name,boolean useDbObjectFlag,String dbExpression,
                                        String desc,boolean nullFlag,
                                        Class<?> dataType,String fieldName,Integer length){

        return valueOf(name,false,"",useDbObjectFlag,dbExpression,false,
                desc,nullFlag,false,false,false,false,dataType,fieldName,length,0,new ArrayList<>());
    }

    public static ColumnMapping valueOf(String name,boolean useDbObjectFlag,String dbExpression,
                                        String desc,boolean nullFlag,
                                        Class<?> dataType,String fieldName,Integer length,AutoFillBean autoFillBean){

        List<IAutoFillBean> autoFillBeanList = new ArrayList<>();
        autoFillBeanList.add(autoFillBean);
        return valueOf(name,false,"",useDbObjectFlag,dbExpression,false,
                desc,nullFlag,false,false,false,false,dataType,fieldName,length,0,autoFillBeanList);
    }

    public static ColumnMapping valueOf(String name,
                                        String desc,boolean nullFlag,
                                        Class<?> dataType,String fieldName){

        return valueOf(name,false,"",false,"",false,
                desc,nullFlag,false,false,false,false,dataType,fieldName,0,0,new ArrayList<>());
    }

    public static ColumnMapping valueOf(String name,
                                        String desc,boolean nullFlag,boolean readonly,
                                        Class<?> dataType,String fieldName,Integer length){

        return valueOf(name,false,"",false,"",false,
                desc,nullFlag,false,false,false,readonly,dataType,fieldName,length,0,new ArrayList<>());
    }

    public static ColumnMapping valueOf(String name,
                                        String desc,boolean nullFlag,boolean readonly,
                                        Class<?> dataType,String fieldName,Integer length,AutoFillBean autoFillBean){

        List<IAutoFillBean> autoFillBeanList = new ArrayList<>();
        autoFillBeanList.add(autoFillBean);
        return valueOf(name,false,"",false,"",false,
                desc,nullFlag,false,false,false,readonly,dataType,fieldName,length,0,autoFillBeanList);
    }

    public static ColumnMapping valueOfVer(){

        return valueOf("VERSION",false,"",false,"",false,
                "版本号",false,false,false,true,false,Integer.class,"version",0,0,new ArrayList<>());
    }



    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public String getFieldName() {
        return this.fieldName;
    }

    @Override
    public boolean getPrimaryKeyFlag() {
        return this.primaryKeyFlag;
    }

    @Override
    public boolean getUniqueFlag() {
        return this.uniqueFlag;
    }

    @Override
    public String getUniqueName(){return this.uniqueName;}

    @Override
    public boolean getUseDbObjectFlag() {
        return this.useDbObjectFlag;
    }

    @Override
    public String getDbExpression() {
        return this.dbExpression;
    }

    @Override
    public Class<?> getDataType() {
        return this.dataType;
    }

    @Override
    public Integer getLength() {
        return this.length;
    }

    @Override
    public boolean getDeleteFlag() {
        return this.deleteFlag;
    }

    @Override
    public boolean getNullFlag() {
        return this.nullFlag;
    }

    @Override
    public boolean getDbGeneratedFlag() {
        return this.dbGeneratedFlag;
    }

    @Override
    public boolean getVersionFlag() {
        return this.versionFlag;
    }


    @Override
    public String getDesc() {
        return this.desc;
    }

    @Override
    public boolean getReadonly() {
        return this.readonly;
    }

    @Override
    public String getAkGroupName() {
        return this.akGroupName;
    }

    @Override
    public Integer getScale(){return this.scale;}



}
